//-----------------------------------------------------------------------
// <copyright file="UpdateLogSettings.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <summary>Modifies logging settings for a website</summary>
//-----------------------------------------------------------------------
namespace Microsoft.Sdc.Tasks.Web.WebSite
{
    using System;
    using Microsoft.Sdc.Tasks.Configuration.Web;

    /// <summary>
    /// Updates the logging settings the specified web site
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[<Web.WebSite.UpdateLogSettings 
    ///     HostName="hostname" 
    ///     Identifier="identifier"
    ///     Description="description"
    ///     logFileTruncateSize="logFileTruncateSize"
    ///     LogExtFileFlags="LogExtFileFlags" 
    ///     LogFileLocaltimeRollover="LogFileLocaltimeRollover"
    ///     LogFilePeriod="LogFilePeriod" /// />]]></code>
    /// <para>where:</para>
    /// <para><i>description</i></para>
    /// <para>Name of Web site to update</para>
    /// <para><i>identifier</i></para>
    /// <para>optional parameter to identify website when 'description' is not used</para>
    /// <para><i>logFileTruncateSize</i></para>
    /// <para>optional parameter to set max size of log files</para>
    /// <para><i>LogFileLocaltimeRollover</i></para>
    /// <para>optional parameter, set to true if logfiles are to use daylight saving time</para>
    /// <para><i>LogFilePeriod</i></para>
    /// <para>ptional parameter to set the period of rollover to a new logfile(defaults to loaclhost)</para>
    /// <para><i>LogExtFileFlags</i></para>
    /// <para>optional parameter to set Bit mask of the attributes to log</para>
    /// <para><i>hostname</i></para>
    /// <para>Host on which the site is configured (defaults to loaclhost)</para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test" >
    ///         <Web.WebSite.UpdateLogSettings
    ///             Desciption="mytestsite"
    ///             logFileTruncateSize=".flv"
    ///             LogExtFileFlags="video/x-flv"/>
    ///     </Target>
    /// </Project>
    /// ]]></code>    
    /// </example>    
    public class UpdateLogSettings : TaskBase
    {
        private string description;
        private string identifier;
        private string logExtFileFlags = null;
        private string logFilePeriod = null;
        private int logFileTruncateSize = 0;
        private bool logFileTruncateSizeSet = false;
        private bool logFileLocaltimeRollover = false;
        private bool logFileLocaltimeRolloverSet = false;
        private string machineName = "localhost";

        /// <summary>
        /// Gets or sets the name of the machine to operate on. Default is localhost
        /// </summary>
        public string MachineName
        {
            get { return this.machineName; }
            set { this.machineName = value; }
        }

        /// <summary>
        /// Time period of Log files
        /// </summary>
        /// <remarks>
        /// The following values are valid.
        /// Or simply supply the integer value required.
        /// 
        /// LogPeriodDay = 0x00000001,
        /// LogPeriodWeek = 0x00000002,
        /// LogPeriodMonth = 0x00000003,
        /// LogPeriodFileSize = 0x00000000 
        /// </remarks>
        public string LogFilePeriod
        {
            get { return this.logFilePeriod; }
            set { this.logFilePeriod = value; }
        }

        /// <summary>
        /// Set to true if logfile should use daylight saving time
        /// </summary>
        public bool LogFileLocaltimeRollover
        {
            get
            {
                return this.logFileLocaltimeRollover;
            }

            set
            {
                this.logFileLocaltimeRolloverSet = true;
                this.logFileLocaltimeRollover = value;
            }
        }

        /// <summary>
        /// Number of bytes log files should grow to before 
        /// starting a new log file
        /// 
        /// Only used if LogFilePeriod is set to LogPeriodFileSize 
        /// </summary>
        public int LogFileTruncateSize
        {
            get
            {
                return this.logFileTruncateSize;
            }

            set
            {
                this.logFileTruncateSizeSet = true;
                this.logFileTruncateSize = value;
            }
        }

        /// <summary>
        /// String describing LogExtFileFlags
        /// </summary>
        /// <value>type</value>
        /// <remarks>
        /// 
        /// The following values are valid. Use a space separated list to combine flags.
        /// Or simply supply the integer value required.
        /// 
        ///  LogExtFileDate = 0x00000001, // Log date
        ///  LogExtFileTime = 0x00000002, // Log time
        ///  LogExtFileClientIp = 0x00000004, // Log client IP address
        ///  LogExtFileUserName = 0x00000008, // Log user name
        ///  LogExtFileSiteName = 0x00000010, // Log site name
        ///  LogExtFileComputerName = 0x00000020, // Log computer name
        ///  LogExtFileServerIp = 0x00000040, // Log server's own IP address
        ///  LogExtFileMethod = 0x00000080, // Log protocol method
        ///  LogExtFileUriStem = 0x00000100, // Log URI stem
        ///  LogExtFileUriQuery = 0x00000200, // Log URI query
        ///  LogExtFileHttpStatus = 0x00000400, // Log HTTP status
        ///  LogExtFileWin32Status = 0x00000800, // Log WIN32 status
        ///  LogExtFileBytesSent = 0x00001000, // Log total bytes sent
        ///  LogExtFileBytesRecv = 0x00002000, // Log total bytes received
        ///  LogExtFileTimeTaken = 0x00004000, // Log total time elapsed
        ///  LogExtFileServerPort = 0x00008000, // Log server port
        ///  LogExtFileUserAgent = 0x00010000, // Log user agent
        ///  LogExtFileCookie = 0x00020000, // Log cookie
        ///  LogExtFileReferer = 0x00040000, // Log referrer
        ///  LogExtFileProtocolVersion = 0x00080000, // Log client server protocol version
        ///  
        ///  // default settings: or this with the settings you want to add to the default set
        ///  LogExtDefault = 0x00218fdf,
        ///
        ///  // The following values are not available for IIS 5.0 (Windows 2000)
        ///  LogExtFileHost = 0x00100000, // [IIS 5.1][IIS 6.0] Log the name of host server.
        ///  LogExtFileHttpSubStatus = 0x00200000, // [IIS 6.0] Log the sub-status code of the HTTP error. For example,
        ///  
        ///  LogExtFileAll_2000 = 0xFFFFF, // [IIS 5.0] Log everything
        ///  LogExtFileAll_XP = 0x1FFFFF, // [IIS 5.1] Log everything
        ///  LogExtFileAll = 0x3FFFFF // [IIS 6.0] Log everything (This seems to work fine on IIS 5.0 and IIS 5.1 also)
        /// </remarks>
        public string LogExtFileFlags
        {
            get { return (this.logExtFileFlags ?? String.Empty); }
            set { this.logExtFileFlags = value; }
        }

        /// <summary>
        /// Description of web site that we are updating
        /// </summary>
        /// <value>A valid web site description</value>
        /// <remarks>If this parameter is not specified you must specify the site <seealso cref="Identifier">Identifier</seealso> 
        /// for the site you wish to apply the binding to</remarks>
        public string Description
        {
            get { return (this.description ?? String.Empty); }
            set { this.description = value; }
        }

        /// <summary>
        /// web site idenfitier for website that we are updating
        /// </summary>
        /// <value>A valid web site identifier</value>
        /// <remarks>If this parameter is not specified you must specify the site <seealso cref="Description">Description</seealso> 
        /// </remarks>
        public string Identifier
        {
            get { return (this.identifier ?? String.Empty); }
            set { this.identifier = value; }
        }

        /// <summary>
        /// Performs the action of this task
        /// </summary>
        protected override void InternalExecute()
        {
            int id = Utilities.CheckWebSiteDescriptionOrIdentifier(this.description, this.identifier, "UpdateLogSettings", this.MachineName);
            if (WebSite.Exists(this.MachineName, id))
            {
                Microsoft.Sdc.Tasks.Configuration.Web.WebSite web = WebSite.Load(this.MachineName, id);
                Microsoft.Sdc.Tasks.Configuration.Web.LogFileSettings logSettings = new Microsoft.Sdc.Tasks.Configuration.Web.LogFileSettings(web);

                if (this.logFileTruncateSizeSet)
                {
                    logSettings.LogFileTruncateSize = this.logFileTruncateSize;
                }

                if (this.logExtFileFlags != null)
                {
                    logSettings.LogExtFileFlags = ParseLogFlags(this.logExtFileFlags);
                }

                if (this.logFilePeriod != null)
                {
                    logSettings.LogFilePeriod = ParsePeriod(this.logFilePeriod);
                }

                if (this.logFileLocaltimeRolloverSet)
                {
                    logSettings.LogFileLocaltimeRollover = this.LogFileLocaltimeRollover;
                }

                logSettings.Update();
                web.Save();
            }
            else
            {
                throw new ArgumentException("The Website does not exist");
            }
        }

        private static LogFileSettings.LogExtFlags ParseLogFlags(string flagString)
        {
            int logFlags;

            // we allow flags to be specified as an int or as a space separated list of named flags
            if (!int.TryParse(flagString, out logFlags))
            {
                string[] flagStringSplit = flagString.Split(' ');
                foreach (string splitItem in flagStringSplit)
                {
                    int flag = (int)Enum.Parse(typeof(LogFileSettings.LogExtFlags), splitItem, true);
                    logFlags = logFlags | flag;
                }
            }

            return (LogFileSettings.LogExtFlags)logFlags;
        }

        private static LogFileSettings.LogPeriod ParsePeriod(string flagString)
        {
            int logFlags;

            // we allow flags to be specified as an int or as a space separated list of named flags
            if (!int.TryParse(flagString, out logFlags))
            {
                logFlags = (int)Enum.Parse(typeof(LogFileSettings.LogPeriod), flagString, true);
            }

            return (LogFileSettings.LogPeriod)logFlags;
        }
    }
}